package com.googlecode.connectlet.crypto.rsa.provider;

import java.math.BigInteger;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;

import com.googlecode.connectlet.util.Bytes;

public class CompactKeySpec implements KeySpec {
	private byte[] encoded;

	public CompactKeySpec(byte[] encoded) {
		this.encoded = encoded;
	}

	public CompactKeySpec(RSAPublicKey key) {
		int len = (key.getModulus().bitLength() + 7) / 8;
		encoded = Bytes.fromBigInteger(key.getModulus(), len);
	}

	public CompactKeySpec(RSAPrivateCrtKey key) {
		int len = (key.getPrimeP().bitLength() + 7) / 8;
		byte[] p = Bytes.fromBigInteger(key.getPrimeP(), len);
		byte[] q = Bytes.fromBigInteger(key.getPrimeQ(), len);
		byte[] dP = Bytes.fromBigInteger(key.getPrimeExponentP(), len);
		byte[] dQ = Bytes.fromBigInteger(key.getPrimeExponentQ(), len);
		byte[] qInv = Bytes.fromBigInteger(key.getCrtCoefficient(), len);
		encoded = Bytes.add(p, q, dP, dQ, qInv);
	}

	public byte[] getEncoded() {
		return encoded;
	}

	public RSAPublicKeyImpl getPublicKey() {
		return new RSAPublicKeyImpl(new BigInteger(1, encoded));
	}

	public RSAPrivateCrtKeyImpl getPrivateKey() {
		int len = encoded.length / 5;
		BigInteger p = new BigInteger(1, Bytes.sub(encoded, 0, len));
		BigInteger q = new BigInteger(1, Bytes.sub(encoded, len, len));
		BigInteger dP = new BigInteger(1, Bytes.sub(encoded, len * 2, len));
		BigInteger dQ = new BigInteger(1, Bytes.sub(encoded, len * 3, len));
		BigInteger qInv = new BigInteger(1, Bytes.sub(encoded, len * 4, len));
		return new RSAPrivateCrtKeyImpl(p, q, dP, dQ, qInv);
	}
}